var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/functionalComponent/table/base/factory.tsx
var factory_exports = {};
__export(factory_exports, {
  default: () => createGridComponent
});
module.exports = __toCommonJS(factory_exports);
var import_memoize_one = __toESM(require("memoize-one"));
var import_react = require("react");
var import_react_dom = require("react-dom");
var import_util = require("../util");
var import_common = require("./common");
var import_domHelpers = require("./domHelpers");
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
var defaultItemKey = ({ columnIndex, rowIndex }) => `${rowIndex}:${columnIndex}`;
var devWarningsOverscanCount = null;
var devWarningsOverscanRowsColumnsCount = null;
var devWarningsTagName = null;
if (process.env.NODE_ENV !== "production") {
  if (typeof window !== "undefined" && typeof window.WeakSet !== "undefined") {
    devWarningsOverscanCount = /* @__PURE__ */ new WeakSet();
    devWarningsOverscanRowsColumnsCount = /* @__PURE__ */ new WeakSet();
    devWarningsTagName = /* @__PURE__ */ new WeakSet();
  }
}
function createGridComponent({
  getColumnOffset,
  getColumnStartIndexForOffset,
  getColumnStopIndexForStartIndex,
  getColumnWidth,
  getEstimatedTotalHeight,
  getEstimatedTotalWidth,
  getOffsetForColumnAndAlignment,
  getOffsetForRowAndAlignment,
  getRowHeight,
  getRowOffset,
  getRowStartIndexForOffset,
  getRowStopIndexForStartIndex,
  initInstanceProps,
  shouldResetStyleCacheOnItemSizeChange
}) {
  var _a;
  return _a = class extends import_react.PureComponent {
    // Always use explicit constructor for React components.
    // It produces less code after transpilation. (#26)
    // eslint-disable-next-line no-useless-constructor
    constructor(props) {
      super(props);
      this._instanceProps = initInstanceProps(this.props, this);
      this._resetIsScrollingTimeoutId = null;
      this._isTree = false;
      this._shouldResetStyleCacheOnItemSizeChange = shouldResetStyleCacheOnItemSizeChange;
      this.state = {
        instance: this,
        isScrolling: false,
        horizontalScrollDirection: "forward",
        scrollLeft: typeof this.props.initialScrollLeft === "number" ? this.props.initialScrollLeft : 0,
        scrollTop: typeof this.props.initialScrollTop === "number" ? this.props.initialScrollTop : 0,
        scrollUpdateWasRequested: false,
        verticalScrollDirection: "forward"
      };
      this._onScroll = (event) => {
        var _a2, _b, _c;
        const { clientHeight, clientWidth, scrollLeft, scrollTop, scrollHeight, scrollWidth } = event.currentTarget;
        const scrollAsync = (_c = (_b = (_a2 = this.props.itemData) == null ? void 0 : _a2.table) == null ? void 0 : _b.props.optimize) == null ? void 0 : _c.scrollAsync;
        const wrap = scrollAsync ? (fn) => fn() : import_react_dom.flushSync;
        wrap(
          () => this.setState((prevState) => {
            if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
              return null;
            }
            const { direction } = this.props;
            let calculatedScrollLeft = scrollLeft;
            if (direction === "rtl") {
              switch ((0, import_domHelpers.getRTLOffsetType)()) {
                case "negative":
                  calculatedScrollLeft = -scrollLeft;
                  break;
                case "positive-descending":
                  calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
                  break;
              }
            }
            calculatedScrollLeft = Math.max(0, Math.min(calculatedScrollLeft, scrollWidth - clientWidth));
            const calculatedScrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
            return {
              isScrolling: true,
              horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? "forward" : "backward",
              scrollLeft: calculatedScrollLeft,
              scrollTop: calculatedScrollTop,
              verticalScrollDirection: prevState.scrollTop < scrollTop ? "forward" : "backward",
              scrollUpdateWasRequested: false
            };
          }, this._resetIsScrollingDebounced)
        );
      };
      this._outerRefSetter = (ref) => {
        const { outerRef } = this.props;
        this._outerRef = ref;
        if (typeof outerRef === "function") {
          outerRef(ref);
        } else if (outerRef != null && typeof outerRef === "object" && outerRef.hasOwnProperty("current")) {
          outerRef.current = ref;
        }
      };
      this._callOnItemsRendered = (0, import_memoize_one.default)(
        (overscanColumnStartIndex, overscanColumnStopIndex, overscanRowStartIndex, overscanRowStopIndex, visibleColumnStartIndex, visibleColumnStopIndex, visibleRowStartIndex, visibleRowStopIndex) => {
          var _a2, _b;
          return (_b = (_a2 = this.props).onItemsRendered) == null ? void 0 : _b.call(_a2, {
            overscanColumnStartIndex,
            overscanColumnStopIndex,
            overscanRowStartIndex,
            overscanRowStopIndex,
            visibleColumnStartIndex,
            visibleColumnStopIndex,
            visibleRowStartIndex,
            visibleRowStopIndex
          });
        }
      );
      this._callOnScroll = (0, import_memoize_one.default)(
        (scrollLeft, scrollTop, horizontalScrollDirection, verticalScrollDirection, scrollUpdateWasRequested) => {
          var _a2, _b;
          return (_b = (_a2 = this.props).onScroll) == null ? void 0 : _b.call(_a2, {
            horizontalScrollDirection,
            scrollLeft,
            scrollTop,
            verticalScrollDirection,
            scrollUpdateWasRequested
          });
        }
      );
      this._getItemStyle = (rowIndex, columnIndex) => {
        const { columnWidth, direction, rowHeight } = this.props;
        const itemStyleCache = this._getItemStyleCache(
          this._shouldResetStyleCacheOnItemSizeChange && columnWidth,
          this._shouldResetStyleCacheOnItemSizeChange && direction,
          this._shouldResetStyleCacheOnItemSizeChange && rowHeight
        );
        const key = `${rowIndex}:${columnIndex}`;
        let style;
        if (itemStyleCache.hasOwnProperty(key)) {
          style = itemStyleCache[key];
        } else {
          const offset = getColumnOffset(this.props, columnIndex, this._instanceProps);
          const isRtl = direction === "rtl";
          itemStyleCache[key] = style = {
            position: "absolute",
            left: isRtl ? void 0 : offset,
            right: isRtl ? offset : void 0,
            top: getRowOffset(this.props, rowIndex, this._instanceProps),
            height: getRowHeight(this.props, rowIndex, this._instanceProps),
            width: getColumnWidth(this.props, columnIndex, this._instanceProps)
          };
        }
        return style;
      };
      this._getItemStyleCache = (0, import_memoize_one.default)((_, __, ___) => ({}));
      this._resetIsScrolling = () => {
        var _a2, _b;
        const me = this;
        me._resetIsScrollingTimeoutId = null;
        (_b = (_a2 = me.props.itemData) == null ? void 0 : _a2.table) == null ? void 0 : _b._resetRowHeight({ immediate: false });
        this.setState({ isScrolling: false }, () => {
          this._getItemStyleCache(-1);
        });
      };
      this._resetIsScrollingDebounced = () => {
        if (this._resetIsScrollingTimeoutId !== null) {
          (0, import_common.cancelTimeout)(this._resetIsScrollingTimeoutId);
        }
        this._resetIsScrollingTimeoutId = (0, import_common.requestTimeout)(this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL);
      };
    }
    scrollTo({ scrollLeft, scrollTop }) {
      if (scrollLeft !== void 0) {
        scrollLeft = Math.max(0, scrollLeft);
      }
      if (scrollTop !== void 0) {
        scrollTop = Math.max(0, scrollTop);
      }
      this.setState((prevState) => {
        if (scrollLeft === void 0) {
          scrollLeft = prevState.scrollLeft;
        }
        if (scrollTop === void 0) {
          scrollTop = prevState.scrollTop;
        }
        if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
          return null;
        }
        return {
          horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? "forward" : "backward",
          scrollLeft,
          scrollTop,
          scrollUpdateWasRequested: true,
          verticalScrollDirection: prevState.scrollTop < scrollTop ? "forward" : "backward"
        };
      }, this._resetIsScrollingDebounced);
    }
    scrollLeftAndTop({ left = 0, top = 0 }, callback) {
      const { scrollHeight, scrollWidth, clientHeight, clientWidth } = this._outerRef;
      const [maxScrollLeft, maxScrollTop] = [scrollWidth - clientWidth, scrollHeight - clientHeight];
      this.setState(
        (prevState) => {
          let [scrollLeft, scrollTop] = [
            Math.min(prevState.scrollLeft + left, maxScrollLeft),
            Math.min(prevState.scrollTop + top, maxScrollTop)
          ];
          if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
            return null;
          }
          if (maxScrollTop === scrollTop) {
            scrollTop = 0;
          }
          if (maxScrollLeft === scrollLeft) {
            scrollLeft = 0;
          }
          return {
            horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? "forward" : "backward",
            scrollLeft,
            scrollTop,
            scrollUpdateWasRequested: true,
            verticalScrollDirection: prevState.scrollTop < scrollTop ? "forward" : "backward"
          };
        },
        () => {
          this._resetIsScrollingDebounced();
          const { scrollLeft, scrollTop } = this.state;
          callback == null ? void 0 : callback({ left: scrollLeft === maxScrollLeft, top: maxScrollTop === scrollTop });
        }
      );
    }
    scrollToItem({
      align = "auto",
      columnIndex,
      rowIndex
    }) {
      const { columnCount, height, rowCount, width } = this.props;
      const { scrollLeft, scrollTop } = this.state;
      const scrollbarSize = (0, import_util.getScrollBarInfo)();
      if (columnIndex !== void 0) {
        columnIndex = Math.max(0, Math.min(columnIndex, columnCount - 1));
      }
      if (rowIndex !== void 0) {
        rowIndex = Math.max(0, Math.min(rowIndex, rowCount - 1));
      }
      const estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps);
      const estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps);
      const horizontalScrollbarSize = estimatedTotalWidth > width ? scrollbarSize.width : 0;
      const verticalScrollbarSize = estimatedTotalHeight > height ? scrollbarSize.height : 0;
      this.scrollTo({
        scrollLeft: columnIndex !== void 0 ? getOffsetForColumnAndAlignment(
          this.props,
          columnIndex,
          align,
          scrollLeft,
          this._instanceProps,
          verticalScrollbarSize
        ) : scrollLeft,
        scrollTop: rowIndex !== void 0 ? getOffsetForRowAndAlignment(
          this.props,
          rowIndex,
          align,
          scrollTop,
          this._instanceProps,
          horizontalScrollbarSize
        ) : scrollTop
      });
    }
    componentDidMount() {
      const { initialScrollLeft, initialScrollTop } = this.props;
      if (this._outerRef != null) {
        const outerRef = this._outerRef;
        if (typeof initialScrollLeft === "number") {
          outerRef.scrollLeft = initialScrollLeft;
        }
        if (typeof initialScrollTop === "number") {
          outerRef.scrollTop = initialScrollTop;
        }
      }
      this._callPropsCallbacks();
    }
    componentDidUpdate() {
      const { direction } = this.props;
      const { scrollLeft, scrollTop, scrollUpdateWasRequested } = this.state;
      if (scrollUpdateWasRequested && this._outerRef != null) {
        const outerRef = this._outerRef;
        if (direction === "rtl") {
          switch ((0, import_domHelpers.getRTLOffsetType)()) {
            case "negative":
              outerRef.scrollLeft = -scrollLeft;
              break;
            case "positive-ascending":
              outerRef.scrollLeft = scrollLeft;
              break;
            default:
              const { clientWidth, scrollWidth } = outerRef;
              outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft;
              break;
          }
        } else {
          outerRef.scrollLeft = Math.max(0, scrollLeft);
        }
        outerRef.scrollTop = Math.max(0, scrollTop);
      }
      this._callPropsCallbacks();
    }
    componentWillUnmount() {
      if (this._resetIsScrollingTimeoutId !== null) {
        (0, import_common.cancelTimeout)(this._resetIsScrollingTimeoutId);
      }
    }
    render() {
      const {
        children,
        className,
        columnCount,
        direction,
        height,
        innerRef,
        innerElementType,
        innerTagName,
        itemData,
        itemKey = defaultItemKey,
        outerElementType,
        outerTagName,
        rowCount,
        style,
        useIsScrolling,
        width
      } = this.props;
      const { isScrolling } = this.state;
      const [columnStartIndex, columnStopIndex] = this._getHorizontalRangeToRender();
      const [rowStartIndex, rowStopIndex] = this._getVerticalRangeToRender();
      const items = [];
      if (columnCount > 0 && rowCount) {
        for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
          for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
            items.push(
              (0, import_react.createElement)(children, {
                columnIndex,
                data: itemData,
                isScrolling: useIsScrolling ? isScrolling : void 0,
                key: itemKey({ columnIndex, data: itemData, rowIndex }),
                rowIndex,
                style: this._getItemStyle(rowIndex, columnIndex)
              })
            );
          }
        }
      }
      const estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps);
      const estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps);
      return (0, import_react.createElement)(
        outerElementType || outerTagName || "div",
        {
          className,
          onScroll: this._onScroll,
          ref: this._outerRefSetter,
          style: {
            position: "relative",
            height,
            width,
            overflow: "auto",
            WebkitOverflowScrolling: "touch",
            willChange: "transform",
            direction,
            ...style
          }
        },
        (0, import_react.createElement)(innerElementType || innerTagName || "div", {
          children: items,
          ref: innerRef,
          style: {
            height: estimatedTotalHeight,
            pointerEvents: isScrolling ? "none" : void 0,
            width: estimatedTotalWidth
          }
        })
      );
    }
    _getHorizontalRangeToRender() {
      const { columnCount, overscanColumnCount, overscanColumnsCount, overscanCount, rowCount } = this.props;
      const { scrollLeft } = this.state;
      const overscanCountResolved = overscanColumnCount || overscanColumnsCount || overscanCount || 1;
      if (columnCount === 0 || rowCount === 0) {
        return [0, 0, 0, 0];
      }
      const startIndex = getColumnStartIndexForOffset(this.props, scrollLeft, this._instanceProps);
      const stopIndex = getColumnStopIndexForStartIndex(this.props, startIndex, scrollLeft, this._instanceProps);
      return [
        Math.max(0, startIndex - overscanCountResolved),
        Math.max(0, Math.min(columnCount - 1, stopIndex + overscanCountResolved)),
        startIndex,
        stopIndex
      ];
    }
    _getVerticalRangeToRender() {
      const { columnCount, overscanCount, overscanRowCount, overscanRowsCount, rowCount } = this.props;
      const { scrollTop } = this.state;
      const overscanCountResolved = overscanRowCount || overscanRowsCount || overscanCount || 1;
      if (columnCount === 0 && rowCount === 0) {
        return [0, 0, 0, 0];
      }
      const startIndex = getRowStartIndexForOffset(this.props, scrollTop, this._instanceProps);
      const stopIndex = getRowStopIndexForStartIndex(this.props, startIndex, scrollTop, this._instanceProps);
      return [
        Math.max(0, startIndex - overscanCountResolved),
        Math.max(0, Math.min(rowCount - 1, stopIndex + overscanCountResolved)),
        startIndex,
        stopIndex
      ];
    }
    _callPropsCallbacks() {
      const { columnCount, onItemsRendered, onScroll, rowCount } = this.props;
      if (typeof onItemsRendered === "function") {
        if (columnCount > 0 && rowCount > 0) {
          const [overscanColumnStartIndex, overscanColumnStopIndex, visibleColumnStartIndex, visibleColumnStopIndex] = this._getHorizontalRangeToRender();
          const [overscanRowStartIndex, overscanRowStopIndex, visibleRowStartIndex, visibleRowStopIndex] = this._getVerticalRangeToRender();
          this._callOnItemsRendered(
            overscanColumnStartIndex,
            overscanColumnStopIndex,
            overscanRowStartIndex,
            overscanRowStopIndex,
            visibleColumnStartIndex,
            visibleColumnStopIndex,
            visibleRowStartIndex,
            visibleRowStopIndex
          );
        }
      }
      if (typeof onScroll === "function") {
        const { horizontalScrollDirection, scrollLeft, scrollTop, scrollUpdateWasRequested, verticalScrollDirection } = this.state;
        this._callOnScroll(
          scrollLeft,
          scrollTop,
          horizontalScrollDirection,
          verticalScrollDirection,
          scrollUpdateWasRequested
        );
      }
    }
  }, _a.defaultProps = {
    direction: "ltr",
    itemData: void 0,
    useIsScrolling: false
  }, _a;
}
